#include<iostream>
using namespace std;
int n, m;
const int N = 200;
int f[N * 5];
//因为分堆了，最大的20个，1+2+4+8+16>20所以得N*5的数组
int w[N * 5], v[N * 5], pos;//w是重量
int main()
{
    //二进制优化只适用于求价值问题，也就是有max的问题
     //二进制优化是指把每个物品的个数分堆，分别为1,2,4,8，在选择的时候能够凑出所有的选法，优化为n->logn
    cin >> n >> m;
    for (int i = 1;i <= n;i++)
    {
        int x, y, z;cin >> x >> y >> z;
        //二进制拆分
        int t = 1;
        while (x >= t)
        {
            pos++;
            w[pos] = y * t;//分堆
            v[pos] = z * t;
            x -= t;//数量更新
            t *= 2;//权重更新
        }
        //如果没有正好分完就用剩下的凑一堆
        if (x)
        {
            pos++;
            w[pos] = y * x;
            v[pos] = z * x;
        }
    }
    //分完堆对于每一堆只有选和不选两种情况，所以可以优化成01背包
    for (int i = 1;i <= pos;i++)//拆分完之后实际只有pos堆
    {
        for (int j = m;j >= w[i];j--)
        {
            f[j] = max(f[j],f[j - w[i]] + v[i]);
        }
    }
    cout << f[m] << endl;
    return 0;
}